home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_06_07 / v6n7019a.txt < prev    next >
Text File  |  1989-09-26  |  14KB  |  486 lines

  1. /* floppydr - floppy "doctor" program: low-low-level access to FDC */
  2. #include <conio.h>
  3. #include <dos.h>
  4. #include <bios.h>
  5. #include <stdio.h>
  6. #include <ctype.h>
  7.  
  8. #define UBYTE unsigned char
  9.  
  10. #define flop_cmd(dr, motflag, moton, c, r, n, b) \
  11.     { drive_sel(dr, motflag, moton); \
  12.     fdc_cmd(c, r, n, b); \
  13.     results(c[0], r);}
  14.  
  15. #define out_dor(cmd) outp(0x3F2, cmd)
  16. #define in_stat() (inp(0x03f4))
  17. #define out_dat(d) outp(0x3f5,d)
  18. #define in_dat() (inp(0x3f5))
  19.     /* notes for Turbo-C:  use outportb() and inportb() */
  20.  
  21. UBYTE buffer[1024];
  22. char get_menu_choice();
  23. UBYTE peekbyte(unsigned, unsigned);
  24. long start_tmo(void);
  25.  
  26. #define READ_DATA 6
  27. #define READ_DELETED_DATA 0xC
  28. #define WRITE_DATA 5
  29. #define WRITE_DELETED_DATA 9
  30. #define READ_TRACK 2
  31. #define READ_ID 0xA
  32. #define FORMAT_TRACK 0xD
  33. #define RECALIBRATE 7
  34. #define SENSE_INTR_STATUS 8
  35. #define SPECIFY 3
  36. #define SENSE_DRIVE_STATUS 4
  37. #define SEEK 0xF
  38.  
  39. typedef struct {
  40.     unsigned int ncmd;
  41.     unsigned int nres;
  42.     char ctype;         /* N, I, R, or W,
  43.                     for "no DMA", "Interrupt", "Read", "Write") */
  44.     } CMD_INFO;
  45.  
  46. CMD_INFO cmdt[16] = {
  47.     {0, 0, ' '}, /* 0x00 */
  48.     {0, 0, ' '}, /* 0x01 */
  49.     {9, 7, 'R'}, /* 0x02 read track */
  50.     {3, 0, 'N'}, /* 0x03 specify */
  51.     {2, 1, 'N'}, /* 0x04 sense drive status */
  52.     {9, 7, 'W'}, /* 0x05 write data */
  53.     {9, 7, 'R'}, /* 0x06 read data */
  54.     {2, 0, 'I'}, /* 0x07 recalibrate */
  55.     {1, 2, 'N'}, /* 0x08 sense interrupt status */
  56.     {9, 7, 'W'}, /* 0x09 write deleted data */
  57.     {2, 7, 'N'}, /* 0x0a read id */
  58.     {0, 0, ' '}, /* 0x0b */
  59.     {9, 7, 'R'}, /* 0x0c read deleted data */
  60.     {6, 7, 'W'}, /* 0x0d format track */
  61.     {0, 0, ' '}, /* 0x0e */
  62.     {3, 0, 'I'}, /* 0x0f seek */
  63.     };
  64.  
  65. #define NDPARM 12
  66. struct DPARM {
  67.     UBYTE spec1;        /* 0 specify byte 1 */
  68.     UBYTE spec2;        /* 1 specify byte 2 */
  69.     UBYTE mot_off_wt;   /* 2 meaningless */
  70.     UBYTE nrec;         /* 3 number of bytes code */
  71.     UBYTE eot;          /* 4 end-of-track */
  72.     UBYTE gpl;          /* 5 gap length */
  73.     UBYTE dtl;          /* 6 data length (if N = 0) */
  74.     UBYTE fgpl;         /* 7 gpl for format */
  75.     UBYTE fd;           /* 8 fill byte for format */
  76.     UBYTE hdsttl;       /* 9 head settle time (milliseconds) */
  77.     UBYTE mot_start;    /* 10 motor start time (1/8 seconds) */
  78.     UBYTE mt_mfm_sk;    /* 11 bits: 0x80 = MT, 0x40 = MFM,
  79.                             0x20 = SK */
  80.     } dparm = {0xcf, 0x02, 0x25, 0x02, 0x12, 0x2A, 
  81.         0xFF, 0x50, 0xF6, 0x01, 0x04, 0xE0};
  82.  
  83. static char *dparmmsg[] = {
  84.     "0 - specify byte 1 (bits 0-3 = HUT, 4-7 = SRT)  ", 
  85.     "1 - specify byte 2 (bit 1-7 = HLT, 0 = 'no dma')", 
  86.     "2 - meaningless (was motor start time)", 
  87.     "3 - N: number of bytes code (2=512)", 
  88.     "4 - EOT: end-of-track", 
  89.     "5 - GPL: gap length", 
  90.     "6 - DTL:data length (if N = 0)", 
  91.     "7 - gpl for format", 
  92.     "8 - fill byte for format", 
  93.     "9 - head settle time (milliseconds) (not used)", 
  94.     "10 - motor start time (1/8 seconds) (not used)", 
  95.     "11 - bits: 0x80 = MT, 0x40 = MFM, 0x20 = SK"};
  96.  
  97. int main()
  98.     {
  99.     UBYTE unit = 0;
  100.     UBYTE track = 0;
  101.     UBYTE head = 0;
  102.     UBYTE sector = 1;
  103.     UBYTE nsector = 9;
  104.  
  105.     UBYTE cd[9], rs[7], c, hdsds;
  106.     int nbyte, i, j;
  107.  
  108.     printf("\n\nfloppy doctor program\n\n");
  109.     out_dor(0);         /* reset card */
  110.     out_dor(0xC);       /* select drive 0, allow ints & DMA */
  111.  
  112.     while (1)
  113.         {
  114.         c = get_menu_choice();
  115.         switch (c)
  116.             {
  117.         case '0':
  118.             printf("  Enter Drive number:");
  119.             getnum("%d", &unit);
  120.             cd[0] = SENSE_DRIVE_STATUS;
  121.             cd[1] = (hdsds = unit + (head << 2));
  122.             flop_cmd(unit, 0, 0, cd, rs, 0, buffer);
  123.             break;
  124.         case '1':
  125.             cd[0] = SPECIFY;
  126.             cd[1] = dparm.spec1;
  127.             cd[2] = dparm.spec2;
  128.             flop_cmd(unit, 0, 0, cd, rs, 0, buffer);
  129.             break;
  130.         case '2':
  131.             cd[0] = RECALIBRATE;
  132.             cd[1] = unit;
  133.             flop_cmd(unit, 1, 200, cd, rs, 0, buffer);
  134.             break;
  135.         case '3':
  136.             printf("  Enter cylinder (track) number: ");
  137.             getnum("%d", &track);
  138.             cd[0] = SEEK;
  139.             cd[1] = hdsds;
  140.             cd[2] = track;
  141.             drive_sel();
  142.             flop_cmd(unit, 1, 200, cd, rs, 0, buffer);
  143.             break;
  144.         case '4':
  145.             printf("  Enter Head number:");
  146.             getnum("%d", &head);
  147.             hdsds = (hdsds & 0x3) | head;
  148.             break;
  149.         case '5':
  150.             cd[0] = READ_DATA + dparm.mt_mfm_sk;
  151.             goto read_write;
  152.         case '6':
  153.             cd[0] = WRITE_DATA + (dparm.mt_mfm_sk & 0xC0);
  154. read_write:
  155.             printf("  Enter sector number: ");
  156.             getnum("%d", §or);
  157.             nbyte = 128 << dparm.nrec;
  158.             cd[1] = hdsds;
  159.             cd[2] = track;
  160.             cd[3] = head;
  161.             cd[4] = sector;
  162.             cd[5] = dparm.nrec;
  163.             cd[6] = dparm.eot;
  164.             cd[7] = dparm.gpl;
  165.             cd[8] = dparm.dtl;
  166.             flop_cmd(unit, 1, 200, cd, rs, nbyte, buffer);
  167.             if ((cd[0] & 0x0f) == READ_DATA) {
  168.                 puts("");
  169.                 dump_buf(nbyte, buffer);
  170.                 }
  171.             break;
  172.         case '7':
  173.             for (i = 0;  i < nsector;  i++)
  174.                 buffer[i * 4 + 2] = i;
  175.             cd[0] = FORMAT_TRACK + (dparm.mt_mfm_sk & 0x40);
  176.             cd[1] = hdsds;
  177.             cd[2] = dparm.nrec;
  178.             cd[3] = nsector;
  179.             cd[4] = dparm.fgpl; /* gap length for format */
  180.             cd[5] = dparm.fd;   /* fill byte for format */
  181.             fdc_cmd(unit, 1, 200, cd, rs, nsector * 4, buffer);
  182.             break;
  183.         case '8':
  184.             printf("Enter number of times to read ids: ");
  185.             getnum("%d", &j);
  186.             drive_sel(unit, 1, 200);
  187.             cd[0] = READ_ID + (dparm.mt_mfm_sk & 0x40);
  188.             cd[1] = hdsds;
  189.             for (i = 0;  i < j;  i++) {
  190.                 fdc_cmd(cd, rs, 0, buffer);
  191.                 buffer[i * 4 + 0] = rs[3];
  192.                 buffer[i * 4 + 1] = rs[4];
  193.                 buffer[i * 4 + 2] = rs[5];
  194.                 buffer[i * 4 + 3] = rs[6];
  195.                 }
  196.             results(cd[0], rs);     /* of the last command */
  197.             for (i = 0;  i < j;  i++)
  198.                 printf("c = %d, h = %d, r = %d, n = %d\n",
  199.                     buffer[i * 4 + 0], buffer[i * 4 + 1],
  200.                     buffer[i * 4 + 2], buffer[i * 4 + 3]);
  201.             puts("Enter a key when ready");
  202.             getch();
  203.             puts("");
  204.             break;
  205.         case 'R':
  206.             dparm_rpt_chg();
  207.             break;
  208.         case 'X':
  209.             exit(0);
  210.             break;
  211.         default:
  212.             printf("\nIllegal command.\n");
  213.             }
  214.         }
  215.     }
  216.  
  217. char get_menu_choice()
  218.     {
  219.     char inp[80];
  220.  
  221.     puts("");
  222.     puts("Menu:");
  223.     puts("     0 - Drive #");
  224.     puts("     1 - Specify (Step rate, Head unload, etc.)");
  225.     puts("     2 - Recalibrate");
  226.     puts("     3 - Seek (cylinder (track) number");
  227.     puts("     4 - Head (surface)");
  228.     puts("     5 - Read sector");
  229.     puts("     6 - Write sector");
  230.     puts("     7 - Format a track");
  231.     puts("     8 - Read IDs");
  232.     puts("     R - Report and change the DPARM table");
  233.     puts("     X - Exit program");
  234.     puts("\n");
  235.     printf("Command:  ");
  236.     gets(inp);
  237.     puts("");
  238.     return (isalpha(inp[0]) ? toupper(inp[0]) : inp[0]);
  239.     }
  240.  
  241. int dparm_rpt_chg()
  242.     {
  243.     int i, pi;
  244.     unsigned int nv;
  245.     UBYTE *a = &dparm.spec1;
  246.  
  247.     for (i = 0;  i < NDPARM;  i++)
  248.         printf("(0x%02x)  ", a[i]),  puts(dparmmsg[i]);
  249.     puts("");
  250.     printf("Which to change (enter -1 if none to change): ");
  251.     getnum("%d", &pi);
  252.     if ((pi < 0) || (pi >= NDPARM))
  253.         return;
  254.     printf("dparm[%d] = %02x, new value:  ", pi, a[pi]);
  255.     getnum("%x", &nv);
  256.     a[pi] = nv;
  257.     }
  258.  
  259. int fdc_cmd(UBYTE cmds[], UBYTE results[], int n